package com.alibaba.idst.nls.demo;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Toast;

import com.alibaba.idst.util.NlsClient;
import com.alibaba.idst.util.SpeechSynthesizer;
import com.alibaba.idst.util.SpeechSynthesizerCallback;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 语音合成
 */
public class SpeechSynthesizerActivity extends AppCompatActivity {
    private static final String TAG="AliSpeechDemo";

    NlsClient client;
    private SpeechSynthesizer speechSynthesizer;//语音合成的桥梁，将文字上传到服务器进行语音的合成
    private EditText mEtContent;//输入文字
    private RadioGroup mRgRate;//设置人声
    private RadioGroup mRgXb;//设置性别
    private EditText mEtSpeed;//设置语速
    private FileOutputStream mFos;//输出流

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_speech_synthesizer);

        initView();

        //创建client实例，client只需要创建一次，可以用它多次创建synthesizer
        client = new NlsClient();
    }

    private void initView() {
        mEtContent = findViewById(R.id.et_content);
        mRgRate = findViewById(R.id.rg_rate);
        mRgXb = findViewById(R.id.fg_xb);
        mEtSpeed = findViewById(R.id.et_speed);
    }

    /**
     * 开始语音合成
     * @param view
     */
    public void startSynthesizer(View view){
        String text = mEtContent.getText().toString();

        //1、设置语音合成的参数
        //设置语音合成的回调
        SpeechSynthesizerCallback callback = new MyCallback();//语音合成的结果回调
        speechSynthesizer = client.createSynthesizerRequest(callback);
        //设置token和appkey
        //请使用https://help.aliyun.com/document_detail/72153.html 动态生成token
        speechSynthesizer.setToken("515adac435104bc28a0deef4fc2ec394");
        //请使用阿里云语音服务管控台(https://nls-portal.console.aliyun.com/)生成您的appkey
        speechSynthesizer.setAppkey("ZsrijlIWDi1ZWaVp");
        //设置相关参数，以下选项都会改变最终合成的语音效果，可以按文档调整试听效果
        //设置语音编码，pcm编码可以直接用audioTrack播放，其他编码不行
        speechSynthesizer.setFormat(SpeechSynthesizer.FORMAT_PCM);
        // 设置语音数据采样率
        int rateId = mRgRate.getCheckedRadioButtonId();
        if (rateId == R.id.rb_16){
            speechSynthesizer.setSampleRate(SpeechSynthesizer.SAMPLE_RATE_16K);
        } else {
            speechSynthesizer.setSampleRate(SpeechSynthesizer.SAMPLE_RATE_8K);
        }
        // 设置人声
        int xbId = mRgXb.getCheckedRadioButtonId();
        if (xbId == R.id.rb_female){
            speechSynthesizer.setVoice(SpeechSynthesizer.VOICE_XIAOYUN);
        } else {
            speechSynthesizer.setVoice(SpeechSynthesizer.VOICE_XIAOGANG);
        }
        //设置音量，500 应该是最大
        speechSynthesizer.setVolume(500);
        // 设置语音合成方法
        speechSynthesizer.setMethod(SpeechSynthesizer.METHOD_RUS);
        // 设置语速,默认为100
        speechSynthesizer.setSpeechRate(Integer.parseInt(mEtSpeed.getText().toString()));
        // 设置要转为语音的文本
        speechSynthesizer.setText(text);
        //创建合成的文件
        createPcmFile();

        //2、开始合成
        int result = speechSynthesizer.start();

        //3、对结果判断
        if( result < 0) {
            Toast.makeText(SpeechSynthesizerActivity.this, "启动语音合成失败！", Toast.LENGTH_LONG).show();
            speechSynthesizer.stop();
            return;
        }

        //4、合成结束
        Log.d(TAG,"speechSynthesizer start done");
        speechSynthesizer.stop();
    }

    /**
     * 创建PCM文件
     */
    private void createPcmFile() {
        Log.e(TAG,"创建要写入的pcm文件");
        //1、创建要写入的PCM文件
        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/hdl_audio_cache/temp.pcm";
        try {
            File file = new File(path);
            if (!file.exists()){
                file.createNewFile();
            }
            //2、封装流
            mFos = new FileOutputStream(file);
            Log.e(TAG,"创建输出流成功");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 文字转语音的回调
     */
    private class MyCallback implements SpeechSynthesizerCallback {
        final int SAMPLE_RATE = 16000;
        boolean playing = false;

        // 初始化播放器
        private int iMinBufSize = AudioTrack.getMinBufferSize(SAMPLE_RATE,
                AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT);

        private AudioTrack audioTrack=new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE,
                AudioFormat.CHANNEL_OUT_MONO
                , AudioFormat.ENCODING_PCM_16BIT,
                iMinBufSize, AudioTrack.MODE_STREAM) ;

        // 语音合成开始的回调
        @Override
        public void onSynthesisStarted(String msg, int code) {
            Log.d(TAG,"OnSynthesisStarted " + msg + ": " + String.valueOf(code));
        }

        /**
         * 获取音频数据
         * @param data 音频数据
         * @param code
         */
        @Override
        public void onBinaryReceived(byte[] data, int code) {
            Log.i(TAG, "binary received length: " + data.length);
            if (!playing) {
                playing = true;
                audioTrack.play();
            }
            //将合成的数据写入文件中
            saveDataToFile(data);
            //获取音频数据的回调，在这里把音频写入播放器
            audioTrack.write(data, 0, data.length);
        }

        // 语音合成完成的回调，在这里关闭播放器
        @Override
        public void onSynthesisCompleted(final String msg, int code) {
            audioTrack.stop();
            Log.e(TAG,"合成完成");
            flushAndClose();
            convertPcm2Wav();
        }

        // 调用失败的回调
        @Override
        public void onTaskFailed(String msg, int code) {
            Log.d(TAG,"OnTaskFailed " + msg + ": " + String.valueOf(code));
        }

        // 连接关闭的回调
        @Override
        public void onChannelClosed(String msg, int code) {
            Log.d(TAG, "OnChannelClosed " + msg + ": " + String.valueOf(code));
        }
    }

    /**
     * 将PCM格式的文件写入WAV
     */
    private void convertPcm2Wav() {
        //Pcm的文件路劲
        String pcmPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/hdl_audio_cache/" + "temp.pcm";
        //输出的wav文件路径
        String wavPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/hdl_audio_cache/" +  "test.wav";
        //把pcm转成wav
        AudioUtil.convertPcm2Wav(pcmPath, wavPath, 16000, 1, 16);
        Log.e(TAG,"转换完成");
    }

    /**
     * 流完全写入并且关闭
     */
    private void flushAndClose() {
        try {
            mFos.flush();
            mFos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.e(TAG,"流刷新和关闭完成");
    }

    /**
     * 将合成的数据写入文件中
     * @param data
     */
    private void saveDataToFile(byte[] data) {
        try{
            mFos.write(data);
        }catch (Exception e){

        }
    }

    @Override
    public void onDestroy(){
        // 最终，释放客户端
        client.release();
        super.onDestroy();
    }

}
